﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Text;

namespace WebCrawler
{
    class HtmlDocRegEx : IHTMLDoc
    {
        private IList<String> _links;
        private String _doc;
        
        //constructor
        public HtmlDocRegEx(String url)
        {
            this.URL = url;
            //HtmlParser();
        }

        public HtmlDocRegEx(String url, String doc)
        {
            this.URL = url;
            this._doc = doc;
            HtmlParser();
        }       

        //set doc value/parse
        public String Doc
        {
            get
            { 
                return _doc; 
            }
            set
            {
                _doc = value;
                HtmlParser();
            }
        }

        //Get/sets.
        public String URL { get; set; }
        public String Title{ get; set; }

        //GetAllLinks
        public IList<string> GetAllLinks()
        {
            return _links;
        }
        
        //Searchstring
        public bool Contains(string searchString)
        {
            throw new NotImplementedException();
        }
         
        //Parser html
        private void HtmlParser()
        {
            this._links = GetLinks(this._doc, this.URL);
            this.Title = GetTitle(this._doc);
        }

        public static string GetTitle(string args)
        {
            string result = "<Ingen titel>";
            string regEx = "(?i)<title>(?<name>.*?)</title>";
            Regex regObj = new Regex(regEx);
            Match match = regObj.Match(args);
            if(match.Success)
            {
                result = match.Groups["name"].Value;
            }
            return result;
        }

        private static IList<string> GetLinks(string args, string calledUri)
        {
            List<string> _links = new List<string>();
            IList<string> _linksFinal = new List<string>();
            _links.AddRange(GetLinksHelper(args, "a"));
            _links.AddRange(GetLinksHelper(args, "frame"));
            _links.AddRange(GetLinksHelper(args, "iframe"));

            foreach (string link in _links)
            {
                string result = link;
                string protocol = (link.StartsWith("https")) ? "https" : "http";

                if (link.StartsWith("javascript:") || link.StartsWith("#") || link.StartsWith("mailto:"))
                {

                }
                else if (!link.StartsWith("http"))
                {
                    string path = link;

                    if (!path.StartsWith("/"))
                    {
                        Uri baseUri = new Uri(calledUri);
                        string basePath = baseUri.AbsolutePath;

                        if (!basePath.EndsWith("/"))
                        {
                            int index = basePath.LastIndexOf("/");
                            basePath = basePath.Remove(index);
                        }

                        path = basePath + "/" + path;
                        path = path.Replace(@"./", @"/");
                        path = path.Replace(@"//", @"/");
                    }

                    UriBuilder uri = new UriBuilder(protocol, GetUriHostname(calledUri), 80, path);
                    _linksFinal.Add(uri.ToString().Replace("%3F", "?"));
                }
                else if (DomainEquals(result, calledUri))
                {
                    _linksFinal.Add(result);
                }
            }

            return _linksFinal;
        }

        public static bool DomainEquals(string uri1, string uri2)
        {
            return GetUriHostname(uri1).Equals(GetUriHostname(uri2));
        }

        public static string GetUriHostname(string uri)
        {
            Uri host = new Uri(uri);
            return host.Host;
        }

        private static List<string> GetLinksHelper(string args, string type)
        {
            List<string> result = new List<string>();

            //string regularExpression = "(?i)<a.*?href=[\"\"'](?<url>.*?)[\"\"'].*?>(?<name>.*?)</a>";
            string regularExpression = "(?i)<a.*?href=[\"\"'](?<url>.*?)[\"\"'].*?>";
            if (type.Equals("frame"))
            {
                regularExpression = "(?i)<frame.*?src=[\"\"'](?<url>.*?)[\"\"'].*?>";
            }
            else if (type.Equals("iframe"))
            {
                regularExpression = "(?i)<iframe.*?src=[\"\"'](?<url>.*?)[\"\"'].*?>";
            }
            Regex regObj = new Regex(regularExpression);

            MatchCollection matches = regObj.Matches(args);
            foreach (Match mat in matches)
            {
                string st = mat.Groups["url"].Value;
                result.Add(st);
            }

            return result;
        }



        public string Document
        {
            get { throw new NotImplementedException(); }
        }

        string IHTMLDoc.Document
         {
             get
             {
                 return this._doc;
             }
             set
             {
                 this._doc = value;
             }
         }
    }
}
